// MVVM就相当于是Vue构造函数
function MVVM(options) {
  // 将创建vm时传入的配置对象存储起来,再后面的代码中使用
  this.$options = options
  // 将配置对象中的data数据往vm实例和变量data中存一份,也是为了在后面的代码中使用
  var data = (this._data = this.$options.data)
  // 将vm实例存储到变量me中,因为后面的代码中有些函数中无法通过this找到vm实例
  var me = this

  // 数据代理
  // 将data数据中所有的键拿出来存储到一个数组中,然后遍历数据
  Object.keys(data).forEach(function (key) {
    // 在遍历数组的过程中,对data对象中的数据,进行代理(将data中所有的数据,代理到vm实例上)
    // _proxy是原型上的一个方法
    me._proxy(key)
  })

  // 数据劫持
  observe(data, this)
  // 解析模板
  this.$compile = new Compile(options.el || document.body, this)
}

MVVM.prototype = {
  $watch: function (key, cb, options) {
    new Watcher(this, key, cb)
  },
  _proxy: function (key) {
    var me = this
    Object.defineProperty(me, key, {
      configurable: false,
      enumerable: true,
      get: function proxyGetter() {
        // 访问vm实例的数据,其实最终拿的是data中的数据
        return me._data[key]
      },
      set: function proxySetter(newVal) {
        // 修改vm实例的数据,其实最终修改的是data中的数据
        me._data[key] = newVal
      },
    })
  },
}
